/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package hu.kovacsp.scala.discovery.examples.di

/**
 * http://scala-programming-language.1934581.n4.nabble.com/Cake-pattern-and-dependency-injection-td1937087.html
 *
 * Taking Martin Folwer's MovieLister dependency injection example, one of the
 * many, many possible ways to recast this in Scala is the following,
 *
 * In the below, I chose to use an abstract factory method "finder" as a hook
 * to obtain the dependency.  I could have used a self-type
 * with a mix-in composition but in this contrived example it
 * doesn't matter much and I happen to find the abstract method more
 * concise and generally easier to reason with.   It also provides an example
 * where the full-blown "cake pattern" isn't required for dependency injection.
 *
 */
object AbstractFactoryMethod {
  def main(args: Array[String]): Unit={
    val filename = "myfile"
    val director = "Steven Spielberg"

    // Do all the wiring
    val lister = new MovieLister {
      val finder = new ColonDelimitedMovieFinder(filename)
    }

    // Do something with the application
    lister.moviesDirectedBy(director).foreach(println _)
  }
}

trait Movie {
  def director: String
  override def toString = "Movie directed by " + director
}

trait MovieFinder {
  def findAll: List[Movie]
}

abstract class MovieLister {
  def moviesDirectedBy(director: String): List[Movie] = {
    finder.findAll.filter(_.director == director)
  }
  def finder: MovieFinder // dependency
}

class ColonDelimitedMovieFinder(val filename: String) extends MovieFinder {
  def findAll = {
    // dummy implementation
    List(new Movie { def director = "Steven Spielberg" })
  }
}
